package com.renfei.multimediatask.util;

import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.TextureView;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;

import com.renfei.multimediatask.camera.Camera2Utils;

import java.nio.ByteBuffer;
import java.time.temporal.TemporalUnit;
import java.util.Arrays;

public class Camera2Loader extends CameraLoader {

    private static final String TAG = "Camera2Loader";


    private int cameraFacing = CameraCharacteristics.LENS_FACING_BACK;
    //摄像头设备
    private CameraDevice mCameraDevice;
    private ImageReader mImageReader;
    //预览请求
    private CaptureRequest.Builder mPreviewRequestBuilder;
    private CameraCaptureSession mCaptureSession;
    //相机管理类
    private CameraManager cameraManager;

    private Activity activity;

    private SurfaceTexture surfaceTexture;

    /**
     * 预览尺寸
     */
    private Size mPreviewSize;

    private int viewWidth;
    private int viewHeight;
    private OnPreviewSelectListener onPreviewSelectListener;
    /**
     * 预览数据
     */
    private Surface mPreviewSurface;

    /**
     * 预览请求
     */
    private CaptureRequest mPreviewRequest;
    private static final String TAG_PREVIEW = "预览";

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public Camera2Loader(Activity activity) {
        this.activity = activity;
        cameraManager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
    }


    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onCreate(int width, int height, OnPreviewSelectListener onPreviewSelectListener) {
        viewWidth = width;
        viewHeight = height;
        this.onPreviewSelectListener = onPreviewSelectListener;
        setUpdateCamera();
    }

    @Override
    public void startPreViewSurfaceHolder(SurfaceHolder surfaceHolder) {

    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void startPreViewTextureView(SurfaceTexture surfaceTexture) {
        this.surfaceTexture = surfaceTexture;
    }


    @Override
    public void onPause() {
        releaseCamera();
    }

    @Override
    public void swithCamera() {

    }

    @Override
    public int getCameraOrientation() {
        return 0;
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public boolean hasMultipleCamera() {
        try {
            return cameraManager.getCameraIdList().length > 1;
        } catch (CameraAccessException e) {
            e.printStackTrace();
            return false;
        }
    }


    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void setUpdateCamera() {
        try {
            String cameraId = null;

            try {
                String[] cameraList = cameraManager.getCameraIdList();
                for (String s : cameraList) {
                    //获取指定相机的参数配置
                    CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(s);

                    if (cameraFacing == characteristics.get(CameraCharacteristics.LENS_FACING)) {
                        //获取StreamConfigurationMap，它是管理摄像头支持的所有输出格式和尺寸
                        StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
                        //根据TextureView的尺寸设置预览尺寸
                        mPreviewSize = Camera2Utils.getOptimalSize(map.getOutputSizes(SurfaceTexture.class), viewWidth / 2, viewHeight / 2);
//                        mPreviewSize = Camera2Utils.getMinSize(map.getOutputSizes(SurfaceTexture.class));

                        Log.e(TAG, "mPreviewSize : width    " + mPreviewSize.getWidth());
                        Log.e(TAG, "mPreviewSize : height   " + mPreviewSize.getHeight());

                        if (null != onPreviewSelectListener) {
                            onPreviewSelectListener.onPreviewSizeSelect(mPreviewSize.getWidth(), mPreviewSize.getHeight());
                        }
                        cameraId = s;
                    }
                }
            } catch (CameraAccessException e) {
                Log.e(TAG, " setUpdateCamera  found  exception");
                e.printStackTrace();
            }

            if (TextUtils.isEmpty(cameraId)) {
                Log.e(TAG, " cameraId  is  empty");
                return;
            }

            if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {
                @Override
                public void onOpened(@NonNull CameraDevice device) {
                    Log.e(TAG, "CameraDevice.StateCallback    onOpened");
                    mCameraDevice = device;
                    startPreview();
                }

                @Override
                public void onDisconnected(@NonNull CameraDevice device) {
                    Log.e(TAG, "CameraDevice.StateCallback    onDisconnected");
                    device.close();
                    mCameraDevice = null;
                }

                @Override
                public void onError(@NonNull CameraDevice device, int i) {
                    Log.e(TAG, "CameraDevice.StateCallback    onError");
                    device.close();
                    mCameraDevice = null;
                }
            }, null);

        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void startPreview() {
        setupImageReader();

        //设置TextureView的缓冲区大小
        surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
        //获取Surface显示预览数据
        mPreviewSurface = new Surface(surfaceTexture);

        try {
            getPreviewRequestBuilder();
            mCameraDevice.createCaptureSession(Arrays.asList(mPreviewSurface, mImageReader.getSurface()),
                    new CameraCaptureSession.StateCallback() {
                        @Override
                        public void onConfigured(CameraCaptureSession session) {
                            mCaptureSession = session;
                            repeatPreview();
                        }

                        @Override
                        public void onConfigureFailed(CameraCaptureSession session) {

                        }
                    }, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void repeatPreview() {
        mPreviewRequestBuilder.setTag(TAG_PREVIEW);
        mPreviewRequest = mPreviewRequestBuilder.build();
        //设置反复捕获数据的请求，这样预览界面就会一直有数据显示
        try {
            mCaptureSession.setRepeatingRequest(mPreviewRequest, mPreviewCaptureCallback, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private CameraCaptureSession.CaptureCallback mPreviewCaptureCallback = new CameraCaptureSession.CaptureCallback() {
        @Override
        public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {

        }

        @Override
        public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {

        }
    };

    // 创建预览请求的Builder（TEMPLATE_PREVIEW表示预览请求）
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void getPreviewRequestBuilder() {
        if (null == mCameraDevice) {
            Log.e(TAG, "mCameraDevice:  is null");
            return;
        }


        try {
            mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        //设置预览的显示界面
        mPreviewRequestBuilder.addTarget(mPreviewSurface);
        mPreviewRequestBuilder.addTarget(mImageReader.getSurface());
        MeteringRectangle[] meteringRectangles = mPreviewRequestBuilder.get(CaptureRequest.CONTROL_AF_REGIONS);
        if (meteringRectangles != null && meteringRectangles.length > 0) {
            Log.d(TAG, "PreviewRequestBuilder: AF_REGIONS=" + meteringRectangles[0].getRect().toString());
        }
        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE);
    }

    /**
     * ImageReader  特别说明，不支持NV21
     */

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void setupImageReader() {
        Log.e(TAG, "setupImageReader    start");
        //前三个参数分别是需要的尺寸和格式，最后一个参数代表每次最多获取几帧数据
        mImageReader = ImageReader.newInstance(mPreviewSize.getWidth(),
                mPreviewSize.getHeight(),
//                ImageFormat.JPEG,
                ImageFormat.YUV_420_888,
                2);


        mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader) {
//                Log.e(TAG, "ImageReader Available!");
                Image image = reader.acquireLatestImage();//获取下一个

                byte[] nv21Data = YUVDataUtil.getDataFromImage(image, YUVDataUtil.COLOR_FormatNV21);

                if (null != onPreviewFrameListener) {
                    /**
                     *  从image 中读取 数据，然后 将其装换为  NV21
                     */
                    onPreviewFrameListener.onPreviewFrame(nv21Data, image.getWidth(), image.getHeight());
                }

                image.close();
            }
        }, null);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private String getCameraId(int cameraFacing) {
        String result = "";

        try {
            String[] cameraList = cameraManager.getCameraIdList();
            for (String s : cameraList) {
                if (cameraFacing == cameraManager.getCameraCharacteristics(s).get(CameraCharacteristics.LENS_FACING)) {
                    result = s;
                }
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        return result;
    }

    private void releaseCamera() {
        if (null != mImageReader) {
            mImageReader.close();
        }

        if (null != mCameraDevice) {
            mCameraDevice.close();
        }
        if (null != mCaptureSession) {
            mCaptureSession.close();
        }

        mImageReader = null;
        mCameraDevice = null;
        mCaptureSession = null;
    }


}
